// v04.v
// Verilog version, rewritten by Li Shen, Aug 2002
// Institute of Computing Technology, Chinese Academy of Sciences
// The original VHDL version is b04.vhd from Politecnico di Torino

module b04 (CLOCK, RESET, RESTART, AVERAGE, ENABLE, DATA_IN, DATA_OUT);
input CLOCK;
input RESET;
input RESTART;
input AVERAGE;
input ENABLE;
input [7:0] DATA_IN; //signed
output [7:0] DATA_OUT; //signed
/////
wire CLOCK;
wire RESET;
wire RESTART;
wire AVERAGE;
wire ENABLE;
wire [7:0] DATA_IN;
reg [7:0] DATA_OUT;
/////
parameter sA=0, sB=1, sC=2;
reg [1:0] stato;
reg [7:0]  RMAX, RMIN, RLAST, REG1, REG2, REG3, REG4, REGD; //signed
reg [8:0]  temp; //signed
reg RES, AVE, ENA;

/////

always @(posedge CLOCK)
begin
  if (RESET)
  begin
    stato = sA;
    RMAX = 0;
    RMIN = 0;
    RLAST = 0;
    REG1 = 0;
    REG2 = 0;
    REG3 = 0;
    REG4 = 0;
    DATA_OUT <= 0;
  end
  else
  begin
    RES = RESTART;
    ENA = ENABLE;
    AVE = AVERAGE;
    case (stato)
    sA: stato = sB;
    sB: begin
	  RMAX = DATA_IN;
	  RMIN = DATA_IN;
	  REG1 = 0;
	  REG2 = 0;
          REG3 = 0;
	  REG4 = 0;
	  RLAST = 0;
          DATA_OUT <= 0;
          stato = sC;
        end
    sC: begin
	  if (ENA)
            RLAST = DATA_IN;
	  if (RES)
          begin
            temp = {RMAX[7],RMAX}+{RMIN[7],RMIN};
	    REGD = temp & 127;
            if (temp[8]) //<0
              DATA_OUT <= -(-REGD>>1);
            else
              DATA_OUT <= REGD>>1;
	  end
	  else if (ENA)
          begin
	    if (AVE)
	      DATA_OUT <= REG4;
	    else
            begin
              temp = {DATA_IN[7],DATA_IN}+{REG4[7],REG4};
	      REGD = temp & 127;
              if (temp[8]) //<0
                DATA_OUT <= -(-REGD>>1);
              else
                DATA_OUT <= REGD>>1;
            end
	  end
	  else
	    DATA_OUT <= RLAST;

          temp = {RMAX[7],RMAX}-{DATA_IN[7],DATA_IN};
          if (temp[8]) //<0
	    RMAX = DATA_IN;
          else
          begin
            temp = {DATA_IN[7],DATA_IN}-{RMIN[7],RMIN};
            if (temp[8]) //<0
	      RMIN = DATA_IN;
          end
	  REG4 = REG3;
	  REG3 = REG2;
	  REG2 = REG1;
	  REG1 = DATA_IN;
	  stato = sC;
        end
    endcase
  end
end
endmodule
